/****************************************************************************
 * Copyright (C) 2011 Maxim Integrated Products, All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL MAXIM INTEGRATED PRODUCTS BE LIABLE FOR ANY CLAIM, DAMAGES
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Except as contained in this notice, the name of Maxim Integrated Products
 * shall not be used except as stated in the Maxim Integrated Products
 * Branding Policy.
 *
 * The mere transfer of this software does not imply any licenses
 * of trade secrets, proprietary technology, copyrights, patents,
 * trademarks, maskwork rights, or any other form of intellectual
 * property whatsoever. Maxim Integrated Products retains all ownership rights.
 *
 *     Description: MAXQ Clock and Power Mode Driver
 *             $Id: maxq_clk.h 4330 2012-06-27 18:55:01Z jeremy.brodt $
 *
 ********************************************************************************
 */

/** 
* \file
* \brief    Driver for configuring the MAXQ system clock and power modes
* \details  This file defines the driver API including definitions, data types
*           and function prototypes.
*/
#ifndef _MAXQ_CLK_H_
#define _MAXQ_CLK_H_

#include "maxq_config.h"


/***** Definitions *****/

/// Clock divider selection: divide by 1
#define CLK_DIV_1         0x0
/// Clock divider selection: divide by 2
#define CLK_DIV_2         0x1
/// Clock divider selection: divide by 4
#define CLK_DIV_4         0x2
/// Clock divider selection: divide by 8
#define CLK_DIV_8         0x3

// Register bit masks
/// \cond
#define CLK_DIV_MASK      3
#define CLK_PWR_MGMT_MASK (1<<2)
#define CLK_SW_BACK_MASK  (1<<3)
#define CLK_STOP_MASK     (1<<4)
#define CLK_RING_MOD_MASK (1<<5)
#define CLK_RING_SEL_MASK (1<<6)
#define CLK_XTRC_MASK     (1<<7)
#define CLK_IDLE_MASK     (1<<8)
/// \endcond

/// Set the clock divider
#define clk_select_div(div)     CKCN&=((~CLK_DIV_MASK)|div); CKCN|=(div)

/// Gets the clock divider
#define clk_get_div()           (CKCN&CLK_DIV_MASK)

/// Enters Power Management Mode
#define clk_pwr_mgmt_mode_enable()    CKCN|=CLK_PWR_MGMT_MASK

/// Exits Power Management Mode
#define clk_pwr_mgmt_mode_disable()   CKCN&=~CLK_PWR_MGMT_MASK

/**
*   \brief    Determines the current internal system clock frequency
*   \returns  current internal system clock frequency
*/
#define clk_sys_freq()          (CLK_XTAL_FREQ >> ((CKCN & 0x04) ? 0x07 : (CKCN & 0x03)))

/// Enables automatic switch back from Power Management Mode
#define clk_sw_back_enable()    CKCN|=CLK_SW_BACK_MASK

/// Disables automatic switch back from Power Management Mode
#define clk_sw_back_disable()   CKCN&=~CLK_SW_BACK_MASK

/// Enters Stop Mode
#define clk_stop_mode()         CKCN|=CLK_STOP_MASK

/// Enters Idle Mode
#define clk_idle_mode()         CKCN|=CLK_IDLE_MASK

/// Selects the external clock source for the system clock
#define clk_select_extern()     CKCN&=~CLK_RING_SEL_MASK

/// Selects the internal ring oscillator for the system clock
#define clk_select_ring()       CKCN|=CLK_RING_SEL_MASK

/**
*   \brief    Checks if the internal ring oscillator is being used for the
*             system clock
*   \returns  0 if internal ring is not being used
*/
#define clk_check_ring()        (CKCN&CLK_RING_MOD_MASK)

/**
*   \brief    Waits for system clock to switch over to the external clock source
*   \details  This function can be called after power on, wake up, or after 
*             calling clk_select_extern(). In all cases, the switch over to the
*             external clock source from the internal ring will not occur until
*             after the external clock source warm-up counter has expired.
*/
#define clk_wait_for_extern()   while(clk_check_ring())

/// Selects the external crystal/clock for the system clock
#define clk_select_extern_xt()  CKCN&=~CLK_XTRC_MASK

/// Selects the external RC for the system clock
#define clk_select_extern_rc()  CKCN|=CLK_XTRC_MASK

#endif  /*_MAXQ_CLK_H_*/

